﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BTv2.Controls;
using BTv2.Model;
using BTv2.Model.Actions;

namespace BTv2.UserControls
{
    /// <summary>
    /// Interaction logic for RuleSettings.xaml
    /// </summary>
    public partial class RuleSettings : UserControl
    {

        private Settings _settings;
        private RulesController _rcontroller;


        public RuleSettings()
        {
            InitializeComponent();
        }

        public RuleSettings(Settings s)
        {
            InitializeComponent();
            _settings = s;
        }

        private void OpenRulesMenu(object sender, MouseButtonEventArgs e)
        {
            RulesMenu.IsOpen = !RulesMenu.IsOpen;
        }


        private async void RulesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var r = RulesListBox.SelectedItem as Rule;

            try
            {
                Model.Condition cc = r.Condition.Copy();
                r.BackupCondition = cc;
                r.BackupActions = new ObservableCollection<Model.Action>(r.Actions);
                RuleSelectedContent.IsEnabled = true;
                RuleSelectedContent.DataContext = r;
                ActionsListBox.IsEnabled = true;
                RulesListBox.IsEnabled = false;
            }
            catch
            {
                //when deselecting its called
            }
            try
            {
                ActionsListBox.ItemsSource = await _rcontroller.GetFilteredActionList(r);
            }
            catch
            {
                RulesListBox.ItemsSource = _rcontroller.Rules;
            }
            //try
            //{
            //    SensorsListBox.ItemsSource = await _scontroller.GetFilteredSensorList(sg);
            //}
            //catch
            //{
            //    SensorsListBox.ItemsSource = _scontroller.Sensors;
            //}

        }
        public async void BackButtonClick(object sender, RoutedEventArgs e)
        {
            _settings.OpenMainSettings();
        }

        public async void RuleSettingsLoaded(object sender, RoutedEventArgs e)
        {
            _rcontroller = RulesController.GetInstance();
            Application.Current.Resources["SensorCollection"] = SensorsController.GetInstance().Sensors;
            Application.Current.Resources["SimpleConditionOperators"] = new List<string> { "<", ">", ">=", "<=", "=" };
            Application.Current.Resources["ComplexConditionOperators"] = new Dictionary<string, string> {{"And","&&"},{"Or","||"} };
            RulesListBox.ItemsSource = _rcontroller.Rules;
            ExecFComboBox.ItemsSource = _rcontroller.DailyExecutionCountDict;
            ActionsListBox.ItemsSource = _rcontroller.Actions;
            RuleSelectedContent.IsEnabled = false;
            ActionsListBox.IsEnabled = false;


        }

        private void EditMouseDown(object sender, MouseButtonEventArgs e)
        {
            var ll = sender as Label;
            ll.Visibility = Visibility.Hidden;
            UIElement element = VisualTreeHelper.GetParent(ll) as UIElement;
           ContentPresenter ds =( VisualTreeHelper.GetChild(element,0) as ContentPresenter);
            Label savel = ( VisualTreeHelper.GetChild(element,2) as Label);
            Label cancell = (VisualTreeHelper.GetChild(element, 3) as Label);
            savel.Visibility = Visibility.Visible;
            cancell.Visibility = Visibility.Visible;
           Model.Condition c =(Model.Condition) ds.DataContext as Model.Condition ;
           if (c is Model.ComplexCondition)
           {
               ComplexCondition cc = c as ComplexCondition;
               cc.Backup = cc.Copy();
               ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "TComplexConditionDisplayDataTemplate");
           }
           else
           {
               SimpleCondition sc = c as SimpleCondition;
               sc.Backup = sc.Copy();
               ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "TSimpleConditionDisplayDataTemplate");
           }
         //  ds.ContentTemplate =(DataTemplate) this.FindResource("TComplexConditionDisplayDataTemplate");
        }

        private void SaveMouseDown(object sender, MouseButtonEventArgs e)
        {
            var savelabel = sender as Label;

            UIElement element = VisualTreeHelper.GetParent(savelabel) as UIElement;
            ContentPresenter ds = (VisualTreeHelper.GetChild(element, 0) as ContentPresenter);

            Label editL = (VisualTreeHelper.GetChild(element, 1) as Label);
            Label cancelL = (VisualTreeHelper.GetChild(element, 3) as Label);
            editL.Visibility = Visibility.Visible;
            savelabel.Visibility = Visibility.Hidden;
            cancelL.Visibility = Visibility.Hidden;


            Model.Condition c = (Model.Condition)ds.DataContext as Model.Condition;
            if (c is Model.ComplexCondition)
            {
                ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "ComplexConditionDisplayDataTemplate");
            }
            else
            {
                ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "SimpleConditionDisplayDataTemplate");
            }
        }

        private void DeleteMouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                var deleteb = sender as Path;
                UIElement element = VisualTreeHelper.GetParent(deleteb) as UIElement;
                element = VisualTreeHelper.GetParent(element) as UIElement;
                element = VisualTreeHelper.GetParent(element) as UIElement;
                Label sl = (VisualTreeHelper.GetChild(element, 2) as Label);
                Model.Condition c = deleteb.DataContext as Model.Condition;
                //Model.Condition newc = (Model.Condition)ds.DataContext as Model.Condition;
                //if (newc is Model.ComplexCondition)
                //{
                //    ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "ComplexConditionDisplayDataTemplate");
                //}
                //else
                //{
                //    ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "SimpleConditionDisplayDataTemplate");
                //}

                if (c.Parent.Parent == null)
                {
                    Rule r = RuleSelectedContent.DataContext as Rule;
                    ComplexCondition cc = r.Condition as ComplexCondition;

                    if (cc.LeftSideCondition == c)
                    {
                        cc.RightSideCondition.Parent = null;
                        r.Condition = cc.RightSideCondition;
                    }
                    else
                    {
                        cc.LeftSideCondition.Parent = null;
                        r.Condition = cc.LeftSideCondition;
                    }

                }
                else
                {
                    ComplexCondition cc = c.Parent.Parent as ComplexCondition;
                    if (cc.LeftSideCondition == c.Parent)
                    {
                     ComplexCondition ccp = c.Parent as ComplexCondition;
                            if(ccp.LeftSideCondition == c){
                                ccp.RightSideCondition.Parent = ccp.Parent;
                                cc.LeftSideCondition = ccp.RightSideCondition;
                            }else{
                                ccp.LeftSideCondition.Parent = ccp.Parent;
                                cc.LeftSideCondition = ccp.LeftSideCondition;
                            }
                    }
                    else
                    {
                        ComplexCondition ccp = c.Parent as ComplexCondition;
                        if (ccp.LeftSideCondition == c)
                        {
                            ccp.RightSideCondition.Parent = ccp.Parent;
                            cc.RightSideCondition = ccp.RightSideCondition;
                        }
                        else
                        {
                            ccp.LeftSideCondition.Parent = ccp.Parent;
                            cc.RightSideCondition = ccp.LeftSideCondition;
                        }
                    }
                }
                SaveMouseDown(sl, e);
            }
            catch { }


        }

        private void CancelMouseDown(object sender, MouseButtonEventArgs e)
        {
            var cancelLabel = sender as Label;

            UIElement element = VisualTreeHelper.GetParent(cancelLabel) as UIElement;
            ContentPresenter ds = (VisualTreeHelper.GetChild(element, 0) as ContentPresenter);

            Label editL = (VisualTreeHelper.GetChild(element, 1) as Label);
            Label saveL = (VisualTreeHelper.GetChild(element, 2) as Label);

            editL.Visibility = Visibility.Visible;
            saveL.Visibility = Visibility.Hidden;
            cancelLabel.Visibility = Visibility.Hidden;

            Model.Condition c = (Model.Condition)ds.DataContext as Model.Condition;
            if (c is Model.ComplexCondition)
            {
                ComplexCondition cc = c as ComplexCondition;
                ComplexCondition bcc = (ComplexCondition)cc.Backup;
                cc.LeftSideCondition = bcc.LeftSideCondition;
                cc.Operator = bcc.Operator;
                cc.RightSideCondition = bcc.RightSideCondition;

                ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "ComplexConditionDisplayDataTemplate");
            }
            else
            {
                SimpleCondition sc = c as SimpleCondition;
                SimpleCondition bsc = (SimpleCondition)sc.Backup;
                sc.Sensor = bsc.Sensor;
                sc.Operator = bsc.Operator;
                sc.Value = bsc.Value;
                ds.SetResourceReference(ContentPresenter.ContentTemplateProperty, "SimpleConditionDisplayDataTemplate");
            }
        }

        private void NSCButton_Click(object sender, RoutedEventArgs e)
        {
            SimpleCondition nsc = new SimpleCondition() {Sensor = SensorsController.GetInstance().Sensors.First(), Operator = SimpleCondition.BiggerThanOperator, Value = 0 };
            NewConditionPresenter.Content = nsc;
            NewConditionPresenter.SetResourceReference(ContentPresenter.ContentTemplateProperty, "NSimpleConditionDisplayDataTemplate");
        }
        private void CleanCurrentCondition()
        {
            NewConditionPresenter.Content = null;
            NewConditionPresenter.ContentTemplate = null;
        }

        ContentPresenter _dragsource;
        private void ConditionMouseDownPreview(object sender, MouseButtonEventArgs e)
        {
            UIElement parent = (UIElement)sender;
            parent = VisualTreeHelper.GetParent(parent) as UIElement;
            parent = VisualTreeHelper.GetParent(parent) as UIElement;
            _dragsource = (ContentPresenter)parent;
            object data = GetDataFromListBox(_dragsource, e.GetPosition(parent));

            if (data != null)
            {
                DragDrop.DoDragDrop(parent, data, DragDropEffects.Move);
            }
        }
        private object GetDataFromListBox(ContentPresenter source, Point point)
        {
            SimpleCondition sc = NewConditionPresenter.Content as SimpleCondition;
            if (sc != null)
            {
                return sc;
            }
            return null;
        }

        private void Condition_Drop(object sender, DragEventArgs e)
        {
            //ListBox parent = (ListBox)sender;
            SimpleCondition data = e.Data.GetData(typeof(SimpleCondition)) as SimpleCondition;

            UIElement parent = (UIElement)sender;
            parent = VisualTreeHelper.GetParent(parent) as UIElement;
            parent = VisualTreeHelper.GetParent(parent) as UIElement;
            ContentPresenter resp = (ContentPresenter)parent;
            Model.Condition c = resp.DataContext as Model.Condition;
            if(c is SimpleCondition){
                
                SimpleCondition sc = c as SimpleCondition;
                if (sc.Parent != null)
                {
                    ComplexCondition ncc = new ComplexCondition();
                    ncc.Parent = sc.Parent;
                    sc.Parent = ncc;
                    ncc.LeftSideCondition = sc;
                    ncc.Operator = ComplexCondition.AndOperator;
                    data.Parent = ncc;
                    ncc.RightSideCondition = data;
                    ComplexCondition pcc = ncc.Parent as ComplexCondition;
                    if (pcc.LeftSideCondition == sc)
                    {
                        pcc.LeftSideCondition = ncc;
                    }
                    else
                    {
                        pcc.RightSideCondition = ncc;
                    }
                    resp.SetResourceReference(ContentPresenter.ContentTemplateProperty, "ComplexConditionDisplayDataTemplate");
                }
                else
                {
                    ComplexCondition ncc = new ComplexCondition();
                    ncc.Parent = sc.Parent;
                    sc.Parent = ncc;
                    ncc.LeftSideCondition = sc;
                    ncc.Operator = ComplexCondition.AndOperator;
                    data.Parent = ncc;
                    ncc.RightSideCondition = data;
                    Rule r = RuleSelectedContent.DataContext as Rule;
                    r.Condition = ncc;
                    resp.SetResourceReference(ContentPresenter.ContentTemplateProperty, "ComplexConditionDisplayDataTemplate");
                }
            }else{
                ComplexCondition cc = c as ComplexCondition;

                if (cc.Parent != null)
                {
                    ComplexCondition ncc = new ComplexCondition();
                    ncc.Parent = cc;
                    cc.LeftSideCondition.Parent = ncc;
                    cc.RightSideCondition.Parent = ncc;

                    ncc.LeftSideCondition = cc.LeftSideCondition;
                    ncc.RightSideCondition = cc.RightSideCondition;
                    ncc.Operator = cc.Operator;
                    cc.LeftSideCondition = ncc;
                    data.Parent = cc;
                    cc.RightSideCondition = data;
                    cc.Operator = ComplexCondition.AndOperator;

                }
                else
                {
                    ComplexCondition ncc = new ComplexCondition();
                    ncc.Parent = cc;
                    cc.LeftSideCondition.Parent = ncc;
                    cc.RightSideCondition.Parent = ncc;

                    ncc.LeftSideCondition = cc.LeftSideCondition;
                    ncc.RightSideCondition = cc.RightSideCondition;
                    ncc.Operator = cc.Operator;
                    cc.LeftSideCondition = ncc;
                    data.Parent = cc;
                    cc.RightSideCondition = data;
                    cc.Operator = ComplexCondition.AndOperator;
                }
            }
            //((IList)dragSource.ItemsSource).Remove(data);
            CleanCurrentCondition();
            //(parent.ItemsSource as ObservableCollection<Sensor>).Add(data);
        }

        ListBox dragSource = null;


        private void AcitionListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ListBox parent = (ListBox)sender;
            dragSource = parent;
            object data = GetData2FromListBox(dragSource, e.GetPosition(parent));

            if (data != null)
            {
                DragDrop.DoDragDrop(parent, data, DragDropEffects.Move);
            }
        }
        private static object GetData2FromListBox(ListBox source, Point point)
        {
            UIElement element = source.InputHitTest(point) as UIElement;
            if (element != null)
            {
                object data = DependencyProperty.UnsetValue;
                while (data == DependencyProperty.UnsetValue)
                {
                    data = source.ItemContainerGenerator.ItemFromContainer(element);
                    if (data == DependencyProperty.UnsetValue)
                    {
                        element = VisualTreeHelper.GetParent(element) as UIElement;
                    }
                    if (element == source)
                    {
                        return null;
                    }
                }
                if (data != DependencyProperty.UnsetValue)
                {
                    return data;
                }
            }
            return null;
        }

        private void CurrentRuleActions_Drop(object sender, DragEventArgs e)
        {
            ListBox parent = (ListBox)sender;
            List<Type> _actypes = _rcontroller.Actions.Select(x => x.GetType()).ToList();
            Model.Action data =(Model.Action) _actypes.Where(y => e.Data.GetData(y) != null).Select(z =>e.Data.GetData(z)).First();
            ((IList)dragSource.ItemsSource).Remove(data);
            (parent.ItemsSource as ObservableCollection<Model.Action>).Add(data);

        }

        private void RuleCancelButton_Click(object sender, RoutedEventArgs e)
        {
            RulesListBox.UnselectAll();
            var r = RuleSelectedContent.DataContext as Rule;
            r.Condition = r.BackupCondition;
            r.Actions = r.BackupActions;
            RuleSelectedContent.DataContext = null;
             ActionsListBox.IsEnabled = false;
            RulesListBox.IsEnabled = true;
            RuleSelectedContent.IsEnabled = false;
            ActionsListBox.ItemsSource = _rcontroller.Actions;
        }
        private async void RSAddButton(object sender, RoutedEventArgs e)
        {
            Rule r = new Rule() {Name="", Description="", Enabled = false, Condition = new Model.SimpleCondition(), DailyExecutionCount =1};
            RuleSelectedContent.IsEnabled = true;
            RuleSelectedContent.DataContext = r;
            ActionsListBox.IsEnabled = true;
            RulesListBox.IsEnabled = false;
            RulesMenu.IsOpen = !RulesMenu.IsOpen;
        }

        private async void RuleDeleteButton_Click(object sender, RoutedEventArgs e)
        {
            RulesListBox.UnselectAll();
            var r = RuleSelectedContent.DataContext as Rule;
             await Task.Run(async() => { await RulesController.GetInstance().DeleteRule(r); });
            RuleSelectedContent.DataContext = null;
            ActionsListBox.IsEnabled = false;
            RulesListBox.IsEnabled = true;
            RuleSelectedContent.IsEnabled = false;
            ActionsListBox.ItemsSource = _rcontroller.Actions;
            MainContentP.DataContext = null;
        }
        private async void RuleSaveButton_Click(object sender, RoutedEventArgs e)
        {
            RulesListBox.UnselectAll();
            var r = RuleSelectedContent.DataContext as Rule;
            int ruleid = r.ID;
            if (ruleid != 0)
            {
                if (RuleNameTextbox.Text == "")
                {
                    if (RuleNameTextbox.Text == "") RuleNameTextbox.Background = new SolidColorBrush(Colors.Red);                  
                    await Task.Delay(4000);
                    RuleNameTextbox.Background = new SolidColorBrush(Colors.White);

                }
                else
                {
                    r.Name = RuleNameTextbox.Text;
                    r.Description = RuleDescriptiontextbox.Text;
                    r.DailyExecutionCount =(int) ExecFComboBox.SelectedValue;
                    r.Enabled =(bool) RuleEnabledToggleSwitch.IsChecked;
               //     r.Condition = MainContentP.DataContext as Model.Condition;
                    bool result = await Task.Run(() => { return _rcontroller.SaveRule(r); });

                    RuleSelectedContent.DataContext = null;
                    ActionsListBox.IsEnabled = false;
                    RulesListBox.IsEnabled = true;
                    RuleSelectedContent.IsEnabled = false;
                    RuleEnabledToggleSwitch.IsChecked = false;
                    ActionsListBox.ItemsSource = _rcontroller.Actions;
                    MainContentP.DataContext = null;
                }
            }
            else
            {
                if (RuleNameTextbox.Text == "")
                {
                    if (RuleNameTextbox.Text == "") RuleNameTextbox.Background = new SolidColorBrush(Colors.Red);
                    await Task.Delay(4000);
                    RuleNameTextbox.Background = new SolidColorBrush(Colors.White);

                }
                else
                {
                    r.Name = RuleNameTextbox.Text;
                    r.Description = RuleDescriptiontextbox.Text;
                    r.DailyExecutionCount = (int)ExecFComboBox.SelectedValue;
                    r.Enabled = (bool)RuleEnabledToggleSwitch.IsChecked;
                    //     r.Condition = MainContentP.DataContext as Model.Condition;
                    bool result = await Task.Run(() => { return _rcontroller.AddRule(r); });
                    if (result) _rcontroller.Rules.Add(r);
                    RuleSelectedContent.DataContext = null;
                    ActionsListBox.IsEnabled = false;
                    RulesListBox.IsEnabled = true;
                    RuleSelectedContent.IsEnabled = false;
                    RuleEnabledToggleSwitch.IsChecked = false;
                    ActionsListBox.ItemsSource = _rcontroller.Actions;
                    MainContentP.DataContext = null;
                }

            }
            //r.Condition = r.BackupCondition;
            //r.Actions = r.BackupActions;
            //RuleSelectedContent.DataContext = null;
            //ActionsListBox.IsEnabled = false;
            //RulesListBox.IsEnabled = true;
            //RuleSelectedContent.IsEnabled = false;
            //ActionsListBox.ItemsSource = _rcontroller.Actions;
        }
    }
}
